<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="/Public/js/three.min.js"></script>
    <script src="/Public/js/three_shaders.js"></script>
    <script src="/Public/js/OrbitControls.js"></script>
    <script src="/Public/js/jquery-3.7.1.min.js"></script>
    <script src="/Public/js/geotiff.js"></script>
    <script src="/Public/js/FluidSimulation_1.js"></script>

    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #1a1a2e;
            font-family: Arial, sans-serif;
        }
        #info {
            position: absolute;
            top: 10px;
            left: 10px;
            color: white;
            background: rgba(0,0,0,0.5);
            padding: 10px;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <div id="info">流体模拟 - 点击添加水波</div>
    
    <script type="module">
        // 初始化 Three.js 场景
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(3,5,3)
        camera.lookAt(0,0,0)
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x1a1a2e);
        document.body.appendChild(renderer.domElement);

        // 添加光照
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        scene.add(ambientLight);
        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
        directionalLight.position.set(1, 3, 2);
        scene.add(directionalLight);

        // 创建流体模拟实例
        const fluidSim = new FluidSimulation(renderer, 512, 512);
        
        // 加载DEM地形
        const file = '/Public/imgs/dem/terrain2.tif';
        const res = await fetch(file)
        const arrayBuffer = await res.arrayBuffer();
        const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer)
        const image = await tiff.getImage()
        const rasters = await image.readRasters()
        const width = image.getWidth()
        const height = image.getHeight()
        const elevationData = new Float32Array(rasters[0])
        
        // 创建地形几何体
        const terrainGeometry = new THREE.PlaneGeometry(5, 5 * height / width, width - 1, height - 1)
        
        // 计算地形高度
        let maxElevation = -Infinity
        for (let i = 0; i < elevationData.length; i++) {
            if (elevationData[i] > maxElevation) {
                maxElevation = elevationData[i]
            }
        }
        let minElevation = Infinity
        for (let i = 0; i < elevationData.length; i++) {
            const num = elevationData[i]
            if (num !== 0 && num < minElevation) {
                minElevation = num
            }
        }
        
        // 设置地形顶点高度
        const positions = terrainGeometry.attributes.position.array
        for (let i = 0; i < elevationData.length; i++) {
            if (maxElevation == minElevation) {
                positions[i * 3 + 2] = 0
            }
            else {
                positions[i * 3 + 2] = (elevationData[i] - minElevation) / (maxElevation - minElevation)
            }
        }
        terrainGeometry.attributes.position.needsUpdate = true
        terrainGeometry.computeVertexNormals()

        // 创建水面材质（与地形几何体结合）
        const waterMaterial = new THREE.ShaderMaterial({
            uniforms: {
                heightMap: { value: fluidSim.getHeightTexture() },
                terrainHeight: { value: terrainGeometry.attributes.position.array },
                time: { value: 0.0 },
                waveIntensity: { value: 0.1 }
            },
            vertexShader: `
                uniform sampler2D heightMap;
                uniform float time;
                uniform float waveIntensity;
                varying vec2 vUv;
                varying float vWaveHeight;
                
                void main() {
                    vUv = uv;
                    
                    // 读取水波高度
                    float waveHeight = texture2D(heightMap, uv).r * waveIntensity;
                    vWaveHeight = waveHeight;
                    
                    // 将水波高度加到地形高度上
                    vec3 pos = position;
                    pos.z += waveHeight;
                    
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
                }
            `,
            fragmentShader: `
                uniform float time;
                varying vec2 vUv;
                varying float vWaveHeight;
                
                void main() {
                    // 根据水波高度计算颜色
                    vec3 waterColor = vec3(0.1, 0.3, 0.8); // 水的基色
                    
                    // 添加水波效果
                    float foam = smoothstep(0.1, 0.2, vWaveHeight);
                    vec3 foamColor = vec3(1.0, 1.0, 1.0);
                    
                    // 混合颜色
                    vec3 finalColor = mix(waterColor, foamColor, foam);
                    
                    // 添加透明度变化
                    float alpha = 0.7 + vWaveHeight * 0.3;
                    
                    gl_FragColor = vec4(finalColor, alpha);
                }
            `,
            transparent: true,
            side: THREE.DoubleSide
        });

        // 创建水面平面（使用地形几何体）
        const waterPlane = new THREE.Mesh(terrainGeometry, waterMaterial);
        waterPlane.rotateX(-Math.PI / 2);
        scene.add(waterPlane);

        // 也可以创建一个半透明的简单平面来显示水波
        const debugPlaneGeometry = new THREE.PlaneGeometry(5, 5 * height / width);
        const debugPlaneMaterial = new THREE.MeshBasicMaterial({
            map: fluidSim.getHeightTexture(),
            transparent: true,
            opacity: 0.7,
            side: THREE.DoubleSide
        });
        const debugPlane = new THREE.Mesh(debugPlaneGeometry, debugPlaneMaterial);
        debugPlane.rotateX(-Math.PI / 2);
        debugPlane.position.y = 0.01; // 稍微高于地形
        scene.add(debugPlane);

        // 鼠标交互
        const mouse = new THREE.Vector2();
        const raycaster = new THREE.Raycaster();
        
        function onMouseMove(event) {
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
        }
        
        function onMouseClick() {
            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObject(waterPlane);
            
            if (intersects.length > 0) {
                const point = intersects[0].point;
                // 将世界坐标转换为UV坐标
                const uvX = (point.x / 2.5) * 0.5 + 0.5;
                const uvY = (point.y / (2.5 * height / width)) * 0.5 + 0.5;
                
                fluidSim.addDisturbance(uvX, uvY, 0.05, 2.0);
            }
        }

        window.addEventListener('mousemove', onMouseMove);
        window.addEventListener('click', onMouseClick);

        // 添加轨道控制器
        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.05;

        // 动画循环
        function animate() {
            requestAnimationFrame(animate);
            
            // 更新流体模拟
            fluidSim.update(0.016);
            
            // 更新水面材质
            waterMaterial.uniforms.heightMap.value = fluidSim.getHeightTexture();
            waterMaterial.uniforms.time.value += 0.01;
            waterMaterial.unedsUpdate = true;
            
            // 更新调试平面
            debugPlaneMaterial.map = fluidSim.getHeightTexture();
            debugPlaneMaterial.needsUpdate = true;
            
            // 更新控制器
            controls.update();
            
            renderer.render(scene, camera);
        }

        // 启动动画
        animate();

        // 窗口大小调整
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });
    </script>
</body>
</html>